package cn.caplike.demo.rabbitmq.springboot.idempotence_reliability.api.messaging.rabbitmq;

import cn.caplike.demo.rabbitmq.springboot.idempotence_reliability.application.MessageDeliveryLogService;
import cn.caplike.demo.rabbitmq.springboot.idempotence_reliability.common.domain.model.MailRequest;
import cn.caplike.demo.rabbitmq.springboot.idempotence_reliability.domain.model.MessageDeliveryLog;
import cn.caplike.demo.rabbitmq.springboot.idempotence_reliability.domain.model.MessageDeliveryLogBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.nio.charset.StandardCharsets;
import java.util.UUID;

/**
 * Description: 邮件发送端
 *
 * @author LiKe
 * @version 1.0.0
 * @date 2020-09-02 13:21
 */
@Slf4j
@RestController
@RequestMapping("/notification")
public class MailProducer {

    private RabbitTemplate rabbitTemplate;

    private MessageDeliveryLogService messageDeliveryLogService;

    @Value("${message.rabbit.mail.exchange.name}")
    private String exchange;

    @Value("${message.rabbit.mail.routing-key}")
    private String routingKey;

    @PostMapping("/mail")
    public void send() {
        final String messageId = UUID.randomUUID().toString();
        final MailRequest mailRequest = MailRequest.builder().messageId(messageId).clientId("local").clientSecret("some-client-secret").receiver("lks.nova@foxmail.com").build();

        // ~ 消息落库
        //   当消息落库失败? 落库成功再发消息, 如果落库成功消息发送失败, 可追溯.
        messageDeliveryLogService.add(
                MessageDeliveryLogBuilder.of()
                        .messageId(messageId).message(mailRequest).exchange(exchange).routingKey(routingKey).status(MessageDeliveryLog.Status.DELIVERING).build()
        );

        // ~ 关于 correlationId: https://stackoverflow.com/questions/53857051/why-cant-i-get-the-correlationid-on-the-consumer-side-by-using-the-spring-boot
        rabbitTemplate.convertAndSend(exchange, routingKey, mailRequest, messagePostProcessor(), new CorrelationData(messageId));
    }

    // ~ MessagePostProcessor
    // -----------------------------------------------------------------------------------------------------------------

    private MessagePostProcessor messagePostProcessor() {
        return message -> {
            final MessageProperties messageProperties = message.getMessageProperties();
            messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON);
            messageProperties.setContentEncoding(StandardCharsets.UTF_8.name());
            return message;
        };
    }

    // ~ Autowired
    // -----------------------------------------------------------------------------------------------------------------

    @Autowired
    public void setMessageDeliveryLogService(MessageDeliveryLogService messageDeliveryLogService) {
        this.messageDeliveryLogService = messageDeliveryLogService;
    }

    @Autowired
    public void setRabbitTemplate(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
    }
}
